home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJLSR106.ARJ / GETOPT.CC < prev    next >
C/C++ Source or Header  |  1992-03-30  |  9KB  |  248 lines

  1. /*
  2. Getopt for GNU. 
  3. Copyright (C) 1987, 1989 Free Software Foundation, Inc.
  4.  
  5. (Modified by Douglas C. Schmidt for use with GNU G++.)
  6. This file is part of the GNU C++ Library.  This library is free
  7. software; you can redistribute it and/or modify it under the terms of
  8. the GNU Library General Public License as published by the Free
  9. Software Foundation; either version 2 of the License, or (at your
  10. option) any later version.  This library is distributed in the hope
  11. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13. PURPOSE.  See the GNU Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. #ifdef __GNUG__
  20. #pragma implementation "GetOpt.h"
  21. #endif
  22. #include <GetOpt.h>
  23.  
  24. char* GetOpt::nextchar = 0;
  25. int GetOpt::first_nonopt = 0;
  26. int GetOpt::last_nonopt = 0;
  27. #if (__GNUG__ == 1) 
  28. OrderingEnum GetOpt::ordering = GetOpt::REQUIRE_ORDER;
  29. #else
  30. GetOpt::OrderingEnum GetOpt::ordering = GetOpt::REQUIRE_ORDER;
  31. #endif /* (__GNUG__ == 1)  */
  32.  
  33. GetOpt::GetOpt (int argc, char **argv, const char *optstring)
  34.  :opterr (1), nargc (argc), nargv (argv), noptstring (optstring)
  35. {
  36.   /* Initialize the internal data when the first call is made.
  37.      Start processing options with ARGV-element 1 (since ARGV-element 0
  38.      is the program name); the sequence of previously skipped
  39.      non-option ARGV-elements is empty.  */
  40.  
  41.   first_nonopt = last_nonopt = optind = 1;
  42.   optarg = nextchar = 0;
  43.  
  44.   /* Determine how to handle the ordering of options and nonoptions.  */
  45.  
  46.   if (optstring[0] == '-')
  47.     ordering = RETURN_IN_ORDER;
  48.   else if (getenv ("_POSIX_OPTION_ORDER") != 0)
  49.     ordering = REQUIRE_ORDER;
  50.   else
  51.     ordering = PERMUTE;
  52. }
  53.  
  54. void
  55. GetOpt::exchange (char **argv)
  56. {
  57.   int nonopts_size
  58.     = (last_nonopt - first_nonopt) * sizeof (char *);
  59.   char **temp = (char **) alloca (nonopts_size);
  60.  
  61.   /* Interchange the two blocks of data in argv.  */
  62.  
  63.   bcopy (&argv[first_nonopt], temp, nonopts_size);
  64.   bcopy (&argv[last_nonopt], &argv[first_nonopt],
  65.          (optind - last_nonopt) * sizeof (char *));
  66.   bcopy (temp, &argv[first_nonopt + optind - last_nonopt],
  67.          nonopts_size);
  68.  
  69.   /* Update records for the slots the non-options now occupy.  */
  70.  
  71.   first_nonopt += (optind - last_nonopt);
  72.   last_nonopt = optind;
  73. }
  74.  
  75. /* Scan elements of ARGV (whose length is ARGC) for option characters
  76.    given in OPTSTRING.
  77.  
  78.    If an element of ARGV starts with '-', and is not exactly "-" or "--",
  79.    then it is an option element.  The characters of this element
  80.    (aside from the initial '-') are option characters.  If `getopt'
  81.    is called repeatedly, it returns successively each of theoption characters
  82.    from each of the option elements.
  83.  
  84.    If `getopt' finds another option character, it returns that character,
  85.    updating `optind' and `nextchar' so that the next call to `getopt' can
  86.    resume the scan with the following option character or ARGV-element.
  87.  
  88.    If there are no more option characters, `getopt' returns `EOF'.
  89.    Then `optind' is the index in ARGV of the first ARGV-element
  90.    that is not an option.  (The ARGV-elements have been permuted
  91.    so that those that are not options now come last.)
  92.  
  93.    OPTSTRING is a string containing the legitimate option characters.
  94.    A colon in OPTSTRING means that the previous character is an option
  95.    that wants an argument.  The argument is taken from the rest of the
  96.    current ARGV-element, or from the following ARGV-element,
  97.    and returned in `optarg'.
  98.  
  99.    If an option character is seen that is not listed in OPTSTRING,
  100.    return '?' after printing an error message.  If you set `opterr' to
  101.    zero, the error message is suppressed but we still return '?'.
  102.  
  103.    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
  104.    so the following text in the same ARGV-element, or the text of the following
  105.    ARGV-element, is returned in `optarg.  Two colons mean an option that
  106.    wants an optional arg; if there is text in the current ARGV-element,
  107.    it is returned in `optarg'.
  108.  
  109.    If OPTSTRING starts with `-', it requests a different method of handling the
  110.    non-option ARGV-elements.  See the comments about RETURN_IN_ORDER, above.  */
  111.  
  112. int
  113. GetOpt::operator () (void)
  114. {
  115.   if (nextchar == 0 || *nextchar == 0)
  116.     {
  117.       if (ordering == PERMUTE)
  118.         {
  119.           /* If we have just processed some options following some non-options,
  120.              exchange them so that the options come first.  */
  121.  
  122.           if (first_nonopt != last_nonopt && last_nonopt != optind)
  123.             exchange (nargv);
  124.           else if (last_nonopt != optind)
  125.             first_nonopt = optind;
  126.  
  127.           /* Now skip any additional non-options
  128.              and extend the range of non-options previously skipped.  */
  129.  
  130.           while (optind < nargc
  131.                  && (nargv[optind][0] != '-'
  132.                      || nargv[optind][1] == 0))
  133.             optind++;
  134.           last_nonopt = optind;
  135.         }
  136.  
  137.       /* Special ARGV-element `--' means premature end of options.
  138.          Skip it like a null option,
  139.          then exchange with previous non-options as if it were an option,
  140.          then skip everything else like a non-option.  */
  141.  
  142.       if (optind != nargc && !strcmp (nargv[optind], "--"))
  143.         {
  144.           optind++;
  145.  
  146.           if (first_nonopt != last_nonopt && last_nonopt != optind)
  147.             exchange (nargv);
  148.           else if (first_nonopt == last_nonopt)
  149.             first_nonopt = optind;
  150.           last_nonopt = nargc;
  151.  
  152.           optind = nargc;
  153.         }
  154.  
  155.       /* If we have done all the ARGV-elements, stop the scan
  156.          and back over any non-options that we skipped and permuted.  */
  157.  
  158.       if (optind == nargc)
  159.         {
  160.           /* Set the next-arg-index to point at the non-options
  161.              that we previously skipped, so the caller will digest them.  */
  162.           if (first_nonopt != last_nonopt)
  163.             optind = first_nonopt;
  164.           return EOF;
  165.         }
  166.      
  167.       /* If we have come to a non-option and did not permute it,
  168.          either stop the scan or describe it to the caller and pass it by.  */
  169.  
  170.       if (nargv[optind][0] != '-' || nargv[optind][1] == 0)
  171.         {
  172.           if (ordering == REQUIRE_ORDER)
  173.             return EOF;
  174.           optarg = nargv[optind++];
  175.           return 0;
  176.         }
  177.  
  178.       /* We have found another option-ARGV-element.
  179.          Start decoding its characters.  */
  180.  
  181.       nextchar = nargv[optind] + 1;
  182.     }
  183.  
  184.   /* Look at and handle the next option-character.  */
  185.  
  186.   {
  187.     char c = *nextchar++;
  188.     char *temp = (char *) index (noptstring, c);
  189.  
  190.     /* Increment `optind' when we start to process its last character.  */
  191.     if (*nextchar == 0)
  192.       optind++;
  193.  
  194.     if (temp == 0 || c == ':')
  195.       {
  196.         if (opterr != 0)
  197.           {
  198.             if (c < 040 || c >= 0177)
  199.               fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
  200.                        nargv[0], c);
  201.             else
  202.               fprintf (stderr, "%s: unrecognized option `-%c'\n",
  203.                        nargv[0], c);
  204.           }
  205.         return '?';
  206.       }
  207.     if (temp[1] == ':')
  208.       {
  209.         if (temp[2] == ':')
  210.           {
  211.             /* This is an option that accepts an argument optionally.  */
  212.             if (*nextchar != 0)
  213.               {
  214.                 optarg = nextchar;
  215.                 optind++;
  216.               }
  217.             else
  218.               optarg = 0;
  219.             nextchar = 0;
  220.           }
  221.         else
  222.           {
  223.             /* This is an option that requires an argument.  */
  224.             if (*nextchar != 0)
  225.               {
  226.                 optarg = nextchar;
  227.                 /* If we end this ARGV-element by taking the rest as an arg,
  228.                    we must advance to the next element now.  */
  229.                 optind++;
  230.               }
  231.             else if (optind == nargc)
  232.               {
  233.                 if (opterr != 0)
  234.                   fprintf (stderr, "%s: no argument for `-%c' option\n",
  235.                            nargv[0], c);
  236.                 c = '?';
  237.               }
  238.             else
  239.               /* We already incremented `optind' once;
  240.                  increment it again when taking next ARGV-elt as argument.  */
  241.               optarg = nargv[optind++];
  242.             nextchar = 0;
  243.           }
  244.       }
  245.     return c;
  246.   }
  247. }
  248.